#ifndef _IO_CONTEXT_H_
#define _IO_CONTEXT_H_

#include <ioeventdef.h>

typedef struct io_context_s io_context_t;

struct io_context_s {
	io_service_ptr		service;
	io_strand_ptr		strand;
	io_work_ptr			work;
};


typedef struct io_contextpool_s io_contextpool_t;

struct io_contextpool_s {

	_threadpool_t	tp;
	io_context_t*	context;
	unsigned short	index;
};


class CPP_NO_VTABLE IoContextBase
{
public:
	IoContextBase() {

	
	}
	virtual ~IoContextBase() {

	}

	int contexts_init(unsigned int count) {

		rc_assert(m_pool, S_ERROR)

		m_pool->context = (io_context_t*)malloc(sizeof(io_context_t) * count);
		unsigned int ul;
		for (ul = 0; ul < count; ul++) {
			io_context_t* context = m_pool->context + ul;
			context->service = ALLOC_NEW io_service;
			context->work = ALLOC_NEW io_work(*context->service);
			context->strand = ALLOC_NEW io_strand(*context->service);
		}

		m_pool->index = 0;
		m_pool->tp.count = count;
		m_pool->tp.func.start = startfunccb;
		m_pool->tp.func.work = workfunccb;
		m_pool->tp.func.stop = stopfunccb;
		m_pool->tp.func.error = errorfunccb;

		return init_threadpool(&m_pool->tp);
	}
	int contexts_start(void* ctx) {

		rc_assert(m_pool, S_ERROR)
		rc_assert(ctx, S_ERROR)
		m_pool->tp.ctx = ctx;
		return 	start_threadpool(&m_pool->tp);
	}
	int contexts_stop() {

		rc_assert(m_pool, S_ERROR)

		unsigned int ul = 0;

		for (ul = 0; ul < m_pool->tp.count; ul++) {
			io_context_t* context = m_pool->context + ul;
			try {
				//context->service->shutdown();
				context->service->stop();
			}
			catch (stdexcep err) {
				loge("std::exception:%s", err.what());
			}
		}
		return stop_threadpool(&m_pool->tp);
	}
	int contexts_uninit() {

		rc_assert(m_pool, S_ERROR)
		uinit_threadpool(&m_pool->tp);

		unsigned int ul = 0;
		for (ul = 0; ul < m_pool->tp.count; ul++) {

			io_context_t* context = m_pool->context + ul;
			if (context->work)
				delete context->work;

			if (context->service)
				delete context->service;

			context = NULL;
		}

		if (m_pool->context)
			free(m_pool->context);

		return 	S_SUCCESS;
	}
	int contexts_post(async_post_func func, void* data) {

		rc_assert(m_pool != NULL, S_ERROR);
		rc_assert(func != NULL, S_ERROR);
		rc_assert(data != NULL, S_ERROR);

		io_service* service = get_instance();
		rc_assert(service != NULL, S_ERROR);

		service->dispatch(boost::bind(func, data));
		return S_SUCCESS;
	}

	int set_instance(io_contextpool_t* pool) {

		rc_assert(pool != NULL, S_ERROR)
		m_pool = pool;
		return S_SUCCESS;
	}

	io_service* get_instance() {

		rc_assert(m_pool, NULL)
		rc_assert(m_pool->context, NULL)
		m_pool->index++;

		unsigned short index = (m_pool->index % m_pool->tp.count);
		return (m_pool->context + index)->service;
	}


	static int startfunccb(void* data, void* context) {

		return S_SUCCESS;
	}

	static int workfunccb(void* data, void* context) {

		int rc = S_SUCCESS;
		io_contextpool_t* pool = (io_contextpool_t*)(data);
		io_thread_t* thread = (io_thread_t*)(context);
		io_context_t *task = (pool->context + thread->id);

		try {
			task->service->run();
		}
		catch (stdexcep err) {
			loge("std::exception:%s", err.what());
			rc = S_ERROR;
		}
		return S_SUCCESS;
	}

	static int stopfunccb(void* data, void* context) {

		return S_SUCCESS;
	}

	static int errorfunccb(void* data, void* context) {

		return S_SUCCESS;
	}

private:
	io_contextpool_t*	m_pool;
};

#endif 
